Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit 969da9a579c34438a5f97b7c57de022b0a92fb4e


Parents : f0e567f
Author : Sudo-Ivan <ivan@quad4.io>
Signature : Signature validation error
Date : 2026-01-05T21:23:53-06:00

feat(audio): better ToneGenerator with high-quality audio processing, including dynamics compression, lowpass filtering, and improved stereo separation

Changes

1 files changed, 85 insertions(+), 18 deletions(-)


Diff

diff --git a/meshchatx/src/frontend/js/ToneGenerator.js b/meshchatx/src/frontend/js/ToneGenerator.js
index 352785d6..06cd4848 100644
--- a/meshchatx/src/frontend/js/ToneGenerator.js
+++ b/meshchatx/src/frontend/js/ToneGenerator.js
@@ -19,6 +19,22 @@ export default class ToneGenerator {
_initAudioContext() {
if (!this.audioCtx) {
this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
+
+ // Create a high-quality output chain
+ this.masterCompressor = this.audioCtx.createDynamicsCompressor();
+ this.masterCompressor.threshold.setValueAtTime(-24, this.audioCtx.currentTime);
+ this.masterCompressor.knee.setValueAtTime(30, this.audioCtx.currentTime);
+ this.masterCompressor.ratio.setValueAtTime(12, this.audioCtx.currentTime);
+ this.masterCompressor.attack.setValueAtTime(0.003, this.audioCtx.currentTime);
+ this.masterCompressor.release.setValueAtTime(0.25, this.audioCtx.currentTime);
+
+ this.masterFilter = this.audioCtx.createBiquadFilter();
+ this.masterFilter.type = "lowpass";
+ this.masterFilter.frequency.setValueAtTime(4000, this.audioCtx.currentTime);
+ this.masterFilter.Q.setValueAtTime(0.7, this.audioCtx.currentTime);
+
+ this.masterCompressor.connect(this.masterFilter);
+ this.masterFilter.connect(this.audioCtx.destination);
}
}
@@ -31,31 +47,63 @@ export default class ToneGenerator {
const play = () => {
const osc1 = this.audioCtx.createOscillator();
const osc2 = this.audioCtx.createOscillator();
+ const sub = this.audioCtx.createOscillator();
+
+ const panner1 = this.audioCtx.createStereoPanner();
+ const panner2 = this.audioCtx.createStereoPanner();
const gain = this.audioCtx.createGain();
+ const subGain = this.audioCtx.createGain();
- osc1.frequency.value = 440;
- osc2.frequency.value = 480;
- gain.gain.value = this.volume;
+ // Main frequencies
+ osc1.type = "sine";
+ osc1.frequency.setValueAtTime(440, this.audioCtx.currentTime);
+
+ osc2.type = "sine";
+ osc2.frequency.setValueAtTime(480, this.audioCtx.currentTime);
- osc1.connect(gain);
- osc2.connect(gain);
- gain.connect(this.audioCtx.destination);
+ // Sub layer for depth and "feel"
+ sub.type = "sine";
+ sub.frequency.setValueAtTime(40, this.audioCtx.currentTime);
+ subGain.gain.setValueAtTime(0.05, this.audioCtx.currentTime);
+
+ // Stereo separation for quality headphones
+ panner1.pan.setValueAtTime(-0.4, this.audioCtx.currentTime);
+ panner2.pan.setValueAtTime(0.4, this.audioCtx.currentTime);
+
+ osc1.connect(panner1);
+ panner1.connect(gain);
+ osc2.connect(panner2);
+ panner2.connect(gain);
+
+ sub.connect(subGain);
+ subGain.connect(gain);
+
+ gain.gain.setValueAtTime(0, this.audioCtx.currentTime);
+ gain.gain.linearRampToValueAtTime(this.volume, this.audioCtx.currentTime + 0.1);
+
+ gain.connect(this.masterCompressor);
osc1.start();
osc2.start();
+ sub.start();
- this.oscillator = [osc1, osc2];
+ this.oscillator = [osc1, osc2, sub];
this.gainNode = gain;
- // Stop after 2 seconds
+ // Stop after 2 seconds with a smooth fade-out
setTimeout(() => {
- if (this.oscillator === osc1 || (Array.isArray(this.oscillator) && this.oscillator.includes(osc1))) {
+ if (Array.isArray(this.oscillator) && this.oscillator.includes(osc1)) {
gain.gain.exponentialRampToValueAtTime(0.001, this.audioCtx.currentTime + 0.5);
setTimeout(() => {
osc1.stop();
osc2.stop();
+ sub.stop();
osc1.disconnect();
osc2.disconnect();
+ sub.disconnect();
+ subGain.disconnect();
+ panner1.disconnect();
+ panner2.disconnect();
gain.disconnect();
}, 500);
}
@@ -76,25 +124,44 @@ export default class ToneGenerator {
const play = () => {
const osc = this.audioCtx.createOscillator();
+ const sub = this.audioCtx.createOscillator();
const gain = this.audioCtx.createGain();
+ const subGain = this.audioCtx.createGain();
+
+ osc.type = "sine";
+ osc.frequency.setValueAtTime(480, this.audioCtx.currentTime);
- osc.frequency.value = 480;
- gain.gain.value = this.volume;
+ sub.type = "sine";
+ sub.frequency.setValueAtTime(40, this.audioCtx.currentTime);
+ subGain.gain.setValueAtTime(0.05, this.audioCtx.currentTime);
osc.connect(gain);
- gain.connect(this.audioCtx.destination);
+ sub.connect(subGain);
+ subGain.connect(gain);
+
+ gain.gain.setValueAtTime(0, this.audioCtx.currentTime);
+ gain.gain.linearRampToValueAtTime(this.volume, this.audioCtx.currentTime + 0.05);
+
+ gain.connect(this.masterCompressor);
osc.start();
+ sub.start();
- this.oscillator = osc;
+ this.oscillator = [osc, sub];
this.gainNode = gain;
- // Stop after 0.5 seconds
+ // Stop after 0.5 seconds with a short fade
setTimeout(() => {
- if (this.oscillator === osc) {
- osc.stop();
- osc.disconnect();
- gain.disconnect();
+ if (Array.isArray(this.oscillator) && this.oscillator.includes(osc)) {
+ gain.gain.exponentialRampToValueAtTime(0.001, this.audioCtx.currentTime + 0.1);
+ setTimeout(() => {
+ osc.stop();
+ sub.stop();
+ osc.disconnect();
+ sub.disconnect();
+ subGain.disconnect();
+ gain.disconnect();
+ }, 100);
}
}, 500);


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────